#include "CDaySignMgr.h"
#include "../mainctrl.h"
#include "CTSizeString.h"
#include "../data/CPlayerOnlineData.h"
#include "MsgAct.pb.h"
#include "../cmd/dataprepare.h"

//获取每日签到信息
int CDaySignMgr::GetDaySignInfo(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        MsgAnsDaySign& stAns)
{
    MsgDaySignInfo* pstMsgDaySign = stAns.mutable_sign_info();
    if (!pstMsgDaySign)
    {
        CT_ERROR(("MsgDaySignInfo Null!"));
        return RET_SYS_NULL_POINTER;
    }

    CTSizeString<MAX_BIT_SET_STRING_LEN> szNameStr;

    int iIntMask = 0;
    char chCharMask = 0;
    int iAccumulateSign = 0;
    int iMonthlySign = stPlayerDetailEx1._stUserDaySign._stMonthlyCount.Get(
            CMainCtrl::m_pstMain->m_iNow);

#define MACRO_DAY_SIGN_IN_SIGN 1    //已签到
#define MACRO_DAY_SIGN_NO_SIGN 0    //未签到

    szNameStr.Set("");
    //注意CMainCtrl::m_pstMain->m_stTm.tm_mday值域为[1,31]
    for (int i = 0; i < CMainCtrl::m_pstMain->m_stTm.tm_mday; ++i)
    {
        //本月签到状态串
        iIntMask = (int)((int)0x1 << i);
        if ((iMonthlySign & iIntMask))//注意只能判断0和非0两种情况
        {
            ++iAccumulateSign;
            szNameStr.Cat("%d",MACRO_DAY_SIGN_IN_SIGN);
        }
        else
        {
            szNameStr.Cat("%d",MACRO_DAY_SIGN_NO_SIGN);
        }
    }

	pstMsgDaySign->set_accumulate_num(iAccumulateSign); //累计签到次数
	//本月签到状态串 0表示未签到 1表示已签到 当天是当月第四天则只给4个0/1串
	pstMsgDaySign->set_sign_str(szNameStr.Get());

    int iMonthlyAward = stPlayerDetailEx1._stUserDaySign._stMonthlyAward.Get(
            CMainCtrl::m_pstMain->m_iNow);

#define MACRO_DAY_SIGN_ALREADY 0    //已领取
#define MACRO_DAY_SIGN_CAN_GET 1    //可领取
#define MACRO_DAY_SIGN_CAN_NOT 2    //未达到领取条件

    szNameStr.Set("");
    for (int i = 0; i < _stDaySignCfg.GetAccumulateDataSize(); ++i)
    {
        //累计签到礼包状态串
        CKeyValue& stKeyValue = _stDaySignCfg.GetAccumulateData(i);
        iIntMask = (int)((int)0x1 << stKeyValue._iValue);

        if ((iMonthlyAward & iIntMask))//注意只能判断0和非0两种情况
        {
            szNameStr.Cat("%d",MACRO_DAY_SIGN_ALREADY);
        }
        else
        {
            if (iAccumulateSign >= stKeyValue._iValue)
            {
                szNameStr.Cat("%d",MACRO_DAY_SIGN_CAN_GET);
            }
            else
            {
                szNameStr.Cat("%d",MACRO_DAY_SIGN_CAN_NOT);
            }
        }
    }

	//累计签到礼包状态串 0表示已领取 1表示可领取 2表示未达到领取条件
	pstMsgDaySign->set_accumulate_str(szNameStr.Get());
    
    UpdateContinueSignData(stPlayerDetailEx1);//先更新一下连续签到数据

    szNameStr.Set("");
    for (int i = 0; i < _stDaySignCfg.GetContinueDataSize(); ++i)
    {
        CKeyValue& stKeyValue = _stDaySignCfg.GetContinueData(i);
        chCharMask = (char)((char)0x1 << stKeyValue._iValue);

        if ((stPlayerDetailEx1._stUserDaySign._chContinueAward & chCharMask))
        {
            szNameStr.Cat("%d",MACRO_DAY_SIGN_ALREADY);
        }
        else
        {
            if (stPlayerDetailEx1._stUserDaySign._chContinueCount >=
                    stKeyValue._iValue)
            {
                szNameStr.Cat("%d",MACRO_DAY_SIGN_CAN_GET);
            }
            else
            {
                szNameStr.Cat("%d",MACRO_DAY_SIGN_CAN_NOT);
            }
        }
    }

	pstMsgDaySign->set_continue_num(
        stPlayerDetailEx1._stUserDaySign._chContinueCount); //连续签到次数

	//连续签到礼包状态串 0表示已领取 1表示可领取 2表示未达到领取条件
	pstMsgDaySign->set_continue_str(szNameStr.Get());

    return 0;
}

//更新连续签到数据
int CDaySignMgr::UpdateContinueSignData(CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    bool bUpdateDBData = false;

    //上次签到时间既不是今天也不是昨天则重置数据
    if (!CTTimeUtils::IsSameDay(stPlayerDetailEx1._stUserDaySign._iLastSignTime,
            CMainCtrl::m_pstMain->m_iNow) &&
        !CTTimeUtils::IsYesterday(
            stPlayerDetailEx1._stUserDaySign._iLastSignTime,
            CMainCtrl::m_pstMain->m_iNow))
    {
        bUpdateDBData = true;
        stPlayerDetailEx1._stUserDaySign._chContinueCount = 0;
        stPlayerDetailEx1._stUserDaySign._chContinueAward = 0;
    }
    
    //上次签到时间是昨天且连续签到次数已经大于等于5次则重置数据
    if (CTTimeUtils::IsYesterday(
            stPlayerDetailEx1._stUserDaySign._iLastSignTime,
            CMainCtrl::m_pstMain->m_iNow) &&
        stPlayerDetailEx1._stUserDaySign._chContinueCount >=
            MAX_DAY_SIGN_CONTINUE_COUNT)
    {
        bUpdateDBData = true;
        stPlayerDetailEx1._stUserDaySign._chContinueCount = 0;
        stPlayerDetailEx1._stUserDaySign._chContinueAward = 0;
    }

    if (bUpdateDBData)
    {
        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_DETAIL_EX1_INFO;
        stKey.m_u64ID = stPlayerDetailEx1._uiGID;
        CMainCtrl::m_pstMain->UpdateData(stKey, stPlayerDetailEx1, VOP_UPDATE);
    }

    return 0;
}

//签到
int CDaySignMgr::PlayerSign(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        MsgAnsDaySign& stAns)
{
    //先处理累计签到
    int iIntMask = 0;
    int iMonthlySign = stPlayerDetailEx1._stUserDaySign._stMonthlyCount.Get(
            CMainCtrl::m_pstMain->m_iNow);

    //注意CMainCtrl::m_pstMain->m_stTm.tm_mday值域为[1,31]
    iIntMask = (int)((int)0x1 << (CMainCtrl::m_pstMain->m_stTm.tm_mday - 1));
    if ((iMonthlySign & iIntMask))//注意只能判断0和非0两种情况
    {
        return ERROR_DAY_SIGN_SIGN_ALREADY;
    }

    //设置累计签到
    iMonthlySign = (iMonthlySign | iIntMask);
    stPlayerDetailEx1._stUserDaySign._stMonthlyCount.Set(iMonthlySign,
        CMainCtrl::m_pstMain->m_iNow);

    //再处理连续签到
    UpdateContinueSignData(stPlayerDetailEx1);//先更新一下连续签到数据

    stPlayerDetailEx1._stUserDaySign._chContinueCount += 1;
    stPlayerDetailEx1._stUserDaySign._iLastSignTime =
        CMainCtrl::m_pstMain->m_iNow;

    return GetDaySignInfo(stPlayerDetailEx1, stAns);
}

//补签
int CDaySignMgr::PlayerRepairSign(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfoEx1& stPlayerDetailEx1, MsgAnsDaySign& stAns)
{
    if (CMainCtrl::m_pstMain->m_stTm.tm_mday - 1 <= 0)//当月第一天不应补签
    {
        return ERROR_DAY_SIGN_UNFIT_REPAIR;
    }

    int iRet = 0;
    bool bNeedRepair = false;
    int iIntMask = 0;
    int iMonthlySign = stPlayerDetailEx1._stUserDaySign._stMonthlyCount.Get(
            CMainCtrl::m_pstMain->m_iNow);

    //注意CMainCtrl::m_pstMain->m_stTm.tm_mday值域为[1,31]
    for (int i = 0; i < CMainCtrl::m_pstMain->m_stTm.tm_mday - 1; ++i)
    {
        iIntMask = (int)((int)0x1 << i);
        if (!(iMonthlySign & iIntMask))//注意只能判断0和非0两种情况
        {
            bNeedRepair = true;
            break;
        }
    }

    if (!bNeedRepair)
    {
        return ERROR_DAY_SIGN_UNFIT_REPAIR;
    }

#define DAY_SIGN_REPAIR_SIGN_GOLD 10    //补签符石数量

    //判断符石数量
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBase,
        OSS_MONEY_MODULE_44, DAY_SIGN_REPAIR_SIGN_GOLD);
    CHECK_RETURN(iRet);

    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBase._uiGID,
        NOTIFY_USER_MONEY);

    //设置累计签到
    iMonthlySign = (iMonthlySign | iIntMask);
    stPlayerDetailEx1._stUserDaySign._stMonthlyCount.Set(iMonthlySign,
        CMainCtrl::m_pstMain->m_iNow);

    return GetDaySignInfo(stPlayerDetailEx1, stAns);
}

//领取连续签到奖励
int CDaySignMgr::GetContinueAward(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        CPlayerOnlineData& stPlayerOnline, MsgReqDaySign& stReq,
        MsgAnsDaySign& stAns)
{
    int iRet = 0;
    if (!stReq.has_award_index())
    {
        return ERROR_DAY_SIGN_REQUEST_DATA;
    }

    int iAwardIndex = stReq.award_index();//前后端约定从1开始 表示领取第x个奖励

    if (iAwardIndex <= 0 || iAwardIndex > _stDaySignCfg.GetContinueDataSize())
    {
        return ERROR_DAY_SIGN_REQUEST_DATA;
    }

    UpdateContinueSignData(stPlayerDetailEx1);//先更新一下连续签到数据

    CKeyValue& stKeyValue = _stDaySignCfg.GetContinueData(iAwardIndex - 1);

    if (stPlayerDetailEx1._stUserDaySign._chContinueCount < stKeyValue._iValue)
    {
        return ERROR_DAY_SIGN_UNFIT_AWARD;
    }

    char chCharMask = (char)((char)0x1 << stKeyValue._iValue);

    if ((stPlayerDetailEx1._stUserDaySign._chContinueAward & chCharMask))
    {
        return ERROR_DAY_SIGN_ALREADY_AWARD;
    }

    CDropItem stDropItem;
#if 0
//#ifdef _DEBUG
    if (TENCENT_LOGIN_FROM_3366 == stPlayerOnline._ucTencentLoginFrom)
    {
        //腾讯3366平台连续签到礼包数量为2
        stDropItem.DropItem(stKeyValue._uiKey, ITEM_TYPE_GIFT, 2);
    }
    else
    {
        stDropItem.DropItem(stKeyValue._uiKey, ITEM_TYPE_GIFT, 1);
    }
//#else
    if (stPlayerOnline._bIsTencentLogin &&
        TENCENT_LOGIN_FROM_3366 == stPlayerOnline._ucTencentLoginFrom)
    {
        //腾讯3366平台连续签到礼包数量为2
        stDropItem.DropItem(stKeyValue._uiKey, ITEM_TYPE_GIFT, 2);
    }
    else
    {
        stDropItem.DropItem(stKeyValue._uiKey, ITEM_TYPE_GIFT, 1);
    }
//#endif
#endif

    stDropItem.DropItem(stKeyValue._uiKey, ITEM_TYPE_GIFT, 1);

    if (CMainCtrl::m_pstMain->m_stItemMgr.CheckBagFull(
            stPlayerOnline._stUserStorage, stDropItem))
    {
        return ERROR_STORAGE_BAG_IS_FULL;
    }

    //设置已领取
    stPlayerDetailEx1._stUserDaySign._chContinueAward =
        (stPlayerDetailEx1._stUserDaySign._chContinueAward | chCharMask);

    //发送物品
    stDropItem.SetOssModule(OSS_MODULE_DAY_SIGN);
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL,
        stPlayerDetailEx1._uiGID, stDropItem);
    CT_RETURN(iRet);

    return GetDaySignInfo(stPlayerDetailEx1, stAns);
}

//领取累计签到奖励
int CDaySignMgr::GetAccumulateAward(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        CPlayerOnlineData& stPlayerOnline, MsgReqDaySign& stReq,
        MsgAnsDaySign& stAns)
{
    if (!stReq.has_award_index())
    {
        return ERROR_DAY_SIGN_REQUEST_DATA;
    }

    int iAwardIndex = stReq.award_index();//前后端约定从1开始 表示领取第x个奖励

    if (iAwardIndex <= 0 || iAwardIndex > _stDaySignCfg.GetAccumulateDataSize())
    {
        return ERROR_DAY_SIGN_REQUEST_DATA;
    }

    CKeyValue& stKeyValue = _stDaySignCfg.GetAccumulateData(iAwardIndex - 1);

    int iRet = 0;
    int iIntMask = 0;
    int iAccumulateSign = 0;
    int iMonthlySign = stPlayerDetailEx1._stUserDaySign._stMonthlyCount.Get(
            CMainCtrl::m_pstMain->m_iNow);
    int iMonthlyAward = stPlayerDetailEx1._stUserDaySign._stMonthlyAward.Get(
            CMainCtrl::m_pstMain->m_iNow);

    //注意CMainCtrl::m_pstMain->m_stTm.tm_mday值域为[1,31]
    for (int i = 0; i < CMainCtrl::m_pstMain->m_stTm.tm_mday; ++i)
    {
        iIntMask = (int)((int)0x1 << i);
        if ((iMonthlySign & iIntMask))//注意只能判断0和非0两种情况
        {
            ++iAccumulateSign;//累计签到次数
        }
    }

    if (iAccumulateSign < stKeyValue._iValue)
    {
        return ERROR_DAY_SIGN_UNFIT_AWARD;//签到次数不足 不能领取
    }

    iIntMask = (int)((int)0x1 << stKeyValue._iValue);

    if ((iMonthlyAward & iIntMask))
    {
        return ERROR_DAY_SIGN_ALREADY_AWARD;//已经领取
    }

    CDropItem stDropItem;
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftItem(stKeyValue._uiKey,
        stPlayerDetailEx1._uiGID, stDropItem, false);
    CT_RETURN(iRet);

    if (CMainCtrl::m_pstMain->m_stItemMgr.CheckBagFull(
            stPlayerOnline._stUserStorage, stDropItem))
    {
        return ERROR_STORAGE_BAG_IS_FULL;
    }

    //设置已领取
    iMonthlyAward = (iMonthlyAward | iIntMask); 
    stPlayerDetailEx1._stUserDaySign._stMonthlyAward.Set(iMonthlyAward,
        CMainCtrl::m_pstMain->m_iNow);

    //发送物品
    stDropItem.SetOssModule(OSS_MODULE_DAY_SIGN);
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL,
        stPlayerDetailEx1._uiGID, stDropItem);
    CT_RETURN(iRet);

    return GetDaySignInfo(stPlayerDetailEx1, stAns);
}

int CDaySignMgr::NotifyAllOnlineUsers()
{
    int iRet = 0;

    MsgReqDaySign stReqTmp;

    const CTArray<unsigned int, MAX_PLAYER_ONLINE>& astAllUsers =
        CMainCtrl::m_pstMain->m_stPlayerOnline.GetAllOnlineUser();

    for (int i = 0; i < astAllUsers.Size(); ++i)
    {
        stReqTmp.set_gid(astAllUsers[i]);
        stReqTmp.set_req_type(CMD_DAY_SIGN_SUB_NOTIFY_INFO);
        iRet = CMainCtrl::m_pstMain->SendInnerCmd(astAllUsers[i],
            ID_MAIN_DAY_SIGN, stReqTmp, true);

        if (iRet)
        {
            CT_ERROR(("send role(%u) inner cmd(%d) error(%d)",astAllUsers[i],
                ID_MAIN_DAY_SIGN,iRet));
        }
    }

    CMainCtrl::m_pstMain->FlushSendCache();

    return 0;
}

